﻿#include <stdio.h>
#include <stdlib.h>
#include "uv.h"
#include <time.h>

uv_loop_t loop;
uv_udp_t server;
sockaddr_in addr;
int nerror;

void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
    // read buffer new
    buf->base = new char[suggested_size];// 建议值一般是65536
    buf->len = suggested_size;
    fprintf(stdout, "alloc buffer\n");
}

void after_send(uv_udp_send_t *req, int status) {
    if (status) {
        fprintf(stderr, "send error %s\n", uv_strerror(status));
    }
    delete[] (char*)req->data; // read buffer delete
    delete req;
    fprintf(stdout, "delete buffer\n");
}

void write_one(const sockaddr* addr, char* pData, int nLen){
    uv_buf_t w_req = uv_buf_init(pData, nLen);
    uv_udp_send_t* udp_s = new uv_udp_send_t;
    udp_s->data = (void*)pData;
    uv_udp_send(udp_s,&server,&w_req, 1, addr, after_send);
}

void fater_recv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf,
             const struct sockaddr* addr, unsigned flags){
    // client info
    char ip_addr[128];
    uv_ip4_name((sockaddr_in*)addr, ip_addr, 128);
    int nport = ntohs(((sockaddr_in*)addr)->sin_port);
    fprintf(stdout, "Recv %s:%d\n", ip_addr, nport);
    buf->base[nread] = '\0';
    fprintf(stdout, "Len=%d, Txt: %s\n", nread, buf->base);

    // write back
    char* curtm = new char[128];
    sprintf(curtm,"curtime: %d", time(NULL));
    write_one(addr, curtm, strlen(curtm)+1);
}

int main(int argc, char* argv[]){
    fprintf(stdout, "udp server demo\n");
    uv_loop_init(&loop);
    uv_udp_init(&loop, &server);
    uv_ip4_addr("0.0.0.0", 9091, &addr);
    fprintf(stdout, "bind addr :9091\n");
    nerror = uv_udp_bind(&server, (const sockaddr*)&addr,0);
    if( nerror == UV__EADDRINUSE ){
        fprintf(stderr,"bind addr 9091 error!\n");
        return 1;
    }
    // uv接管recv事件
    uv_udp_recv_start(&server, alloc_buffer, fater_recv);

    fprintf(stdout, "run\n");
    nerror = uv_run(&loop, UV_RUN_DEFAULT);

    uv_loop_close(&loop);
    return nerror;
}

